﻿namespace JoinBox.Basal;

using System;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Text;


public class GetIpOrSegment
{
    public string? NetworkSegment
    {
        get
        {
            if (IPV4 is null)
                return null;
            // 获取字符串最后一个.的位置  // 取当前目录的字符串第一个字符到最后一个.所在位置
            return IPV4.Substring(0, IPV4.LastIndexOf("."));
            // return IPV4[..IPV4.LastIndexOf(".")];
        }
    }
    /// <summary>
    /// 网段
    /// </summary>
    public string? IPV4 { get; private set; }
    /// <summary>
    ///  获取本机ip或网段
    /// </summary>
    /// <param name="host">本机ip</param>
    /// <param name="port">端口</param>
    public GetIpOrSegment(string? host = null, int? port = null)// "127.0.0.1"
    {
        host ??= "8.8.8.8";
        port ??= PortTool.GetFirstAvailablePort();

        using var socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, 0);
        socket.Connect(host, port.Value);
        var endPoint = socket.LocalEndPoint as IPEndPoint;
        if (endPoint is not null)
            IPV4 = endPoint.Address.ToString();
    }
}

public partial class IntranetPath
{
#pragma warning disable CA2101 // 指定对 P/Invoke 字符串参数进行封送处理
    [DllImport("mpr.dll", CharSet = CharSet.Auto, SetLastError = true, EntryPoint = "WNetGetConnection")]
    static extern int WNetGetConnection
        ([MarshalAs(UnmanagedType.LPTStr)] string localName, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder remoteName, ref int length);
#pragma warning restore CA2101 // 指定对 P/Invoke 字符串参数进行封送处理

    /// <summary>
    /// 映射路径转为网络路径
    /// </summary>
    /// <param name="originalPath">路径</param>
    /// <returns>本地磁盘路径不变,网络驱动器路径返回局域网路径</returns>
    /// 例如:给定路径 P:\2008年2月29日(P:为映射的网络驱动器卷标),返回:"// networkserver/照片/2008年2月9日"
    public static string GetUNCPath(string? originalPath)
    {
        if (originalPath is null || string.IsNullOrEmpty(originalPath))
            throw new ArgumentNullException(nameof(originalPath));

        const int MAX_PATH = 260;
        var sb = new StringBuilder(MAX_PATH);
        if (!(originalPath.Length > 2 && originalPath[1] == ':'))
            return originalPath;

        int size = sb.Capacity;
        char orig = originalPath[0];
        if (!(('a' <= orig && orig <= 'z') || ('A' <= orig && orig <= 'Z')))
            return originalPath;

        int error = WNetGetConnection(originalPath.Substring(0, 2), sb, ref size);
        // int error = WNetGetConnection(originalPath[..2], sb, ref size);
        if (error != 0)
            return originalPath;

        var path = Path.GetFullPath(originalPath);
        if (path == null)
            return originalPath;

        var a = Path.GetPathRoot(originalPath);
        if (a != null)
            path = path.Substring(a.Length);

        return Path.Combine(sb.ToString().TrimEnd(), path);
    }




    [StructLayout(LayoutKind.Sequential)]
    public class NetResource
    {
        public int dwScope;
        public int dwType;
        public int dwDisplayType;
        public int dwUsage;
        public string? LocalName;
        public string? RemoteName;
        public string? Comment;
        public string? provider;
    }

    [DllImport("mpr.dll", CharSet = CharSet.Auto, BestFitMapping = false, EntryPoint = "WNetAddConnection2")]
    static extern int WNetAddConnection2(NetResource netResource, string password, string username, int flag);

    /// <summary>
    /// 映射网络驱动器
    /// </summary>
    /// <param name="localName">本地盘符 如U:</param>
    /// <param name="remotePath">远程路经 如\\\\172.18.118.106\\f</param>
    /// <param name="userName">远程服务器用户名</param>
    /// <param name="password">远程服务器密码</param>
    /// <returns>true映射成功,false映射失败</returns>
    public static bool WNetReflectDrive(string localName, string remotePath, string userName, string password)
    {
        var netResource = new NetResource
        {
            dwScope = 2,
            dwType = 0x1,
            dwDisplayType = 3,
            dwUsage = 1,
            LocalName = localName,
            RemoteName = remotePath,
            provider = null
        };
        int ret = WNetAddConnection2(netResource, password, userName, 0);
        if (ret == 0)
            return true;
        return false;
    }

    [DllImport("mpr.dll", CharSet = CharSet.Auto, BestFitMapping = false, EntryPoint = "WNetCancelConnection2")]
    static extern int WNetCancelConnection2(string lpname, int flag, bool force);
    /// <summary>
    /// 断开网路驱动器
    /// </summary>
    /// <param name="lpName">映射的盘符</param>
    /// <param name="flag">true时如果打开映射盘文件夹,也会断开,返回成功 false时打开映射盘文件夹,返回失败</param>
    /// <returns></returns>
    public static bool WNetDisconnectDrive(string lpName, bool flag)
    {
        int ret = WNetCancelConnection2(lpName, 0, flag);
        if (ret == 0)
            return true;
        return false;
    }
    // https://www.cnblogs.com/190196539/archive/2011/12/20/2294169.html
}